package com.umeox.watch.moto.dataservice.services;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.text.TextUtils;

import com.alibaba.fastjson.JSONObject;
import com.amap.api.fence.GeoFence;
import com.amap.api.fence.GeoFenceClient;
import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.location.DPoint;
import com.umeox.moto.common.log.Logger;
import com.umeox.moto.common.utils.NetUtils;
import com.umeox.moto.mqtt.base.AError;
import com.umeox.moto.mqtt.base.ARequest;
import com.umeox.moto.mqtt.base.AResponse;
import com.umeox.watch.location.proto.LocationProto;
import com.umeox.watch.moto.dataservice.DataProvider;
import com.umeox.watch.moto.dataservice.base.BaseApp;
import com.umeox.watch.moto.dataservice.db.AppDataBase;
import com.umeox.watch.moto.dataservice.db.model.Fences;
import com.umeox.watch.moto.dataservice.mqtt.bean.eventbean.SafeZoneLocation;
import com.umeox.watch.moto.dataservice.mqtt.interfaces.IPublishListener;
import com.umeox.watch.moto.dataservice.observer.CellInfoObserver;
import com.umeox.watch.moto.dataservice.utils.Utils;

import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 处理电子围栏业务
 */
public class GeoFenceService extends Service {

    private static final String TAG = "GeoFenceService";

    private static final String ACTION_SET_GEO_FENCE = "SET_GEO_FENCE";
    private static final int START_LOCATION = 0x100;
    // 地理围栏客户端
    private GeoFenceClient fenceClient = null;
    // 地理围栏的广播action
    private static final String GEOFENCE_BROADCAST_ACTION = "com.umeox.watch.geofence";
    private AMapLocationClient mLocationClient;
    private AMapLocationClientOption mLocationOption;
    private boolean isRegistered;

    /**
     * 设置安全区域
     */
    public static void setGeoFence(Context context) {
        Intent intent = new Intent(context, GeoFenceService.class);
        intent.setAction(ACTION_SET_GEO_FENCE);
        context.startService(intent);
    }

//    public GeoFenceService() {
//        super(TAG);
//    }

    @Override
    public void onCreate() {
        super.onCreate();
        Logger.d(TAG, "开始设置安全区域");
        HandlerThread thread = new HandlerThread("GeoFenceService");
        thread.start();
        // 初始化地理围栏
        fenceClient = new GeoFenceClient(getApplicationContext());
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        String action = intent != null ? intent.getAction() : "";
        Logger.e(TAG, "action:" + action);
        if (ACTION_SET_GEO_FENCE.equals(action)) {
            //首先要取消之前设置的安全区域
            if (fenceClient == null) {
                fenceClient = new GeoFenceClient(getApplicationContext());
            }
            //会清除所有围栏
            fenceClient.removeGeoFence();
            //查询出所有的电子地理围栏
            List<Fences> fencesList = AppDataBase.getInstance().fencesDao().queryAll();
            if (fencesList != null && !fencesList.isEmpty()) {
                IntentFilter filter = new IntentFilter();
                filter.addAction(GEOFENCE_BROADCAST_ACTION);
                registerReceiver(mGeoFenceReceiver, filter);
                isRegistered = true;
                /**
                 * 创建pendingIntent
                 */
                fenceClient.createPendingIntent(GEOFENCE_BROADCAST_ACTION);
                fenceClient.setGeoFenceListener((list, errorCode, customId) -> {
                    if (errorCode == GeoFence.ADDGEOFENCE_SUCCESS) {//判断围栏是否创建成功
                        //geoFenceList是已经添加的围栏列表，可据此查看创建的围栏
                        Logger.i(TAG, customId + "围栏添加成功！！");
                    } else {
                        Logger.i(TAG, customId + "围栏添加失败！！");
                    }
                });
                /**
                 * 设置地理围栏的触发行为,默认为进入
                 */
                fenceClient.setActivateAction(GeoFenceClient.GEOFENCE_IN | GeoFenceClient.GEOFENCE_OUT);
                for (Fences fence : fencesList) {
                    Logger.e(TAG, fence.toString());
                    setGeoFence(fence);
                }
            } else {
                stopSelf();
            }
        }


        return super.onStartCommand(intent, flags, startId);
    }


    private void setGeoFence(Fences fences) {
        if (fences.getType() == 1) { //圆形电子围栏
            DPoint centerPoint = new DPoint(fences.getLat(),
                    fences.getLng());
            float fenceRadius = (float) fences.getRadius();
            fenceClient.addGeoFence(centerPoint, fenceRadius, String.valueOf(fences.getId()));
        }
    }


    @Override
    public void onDestroy() {
        Logger.e(TAG, "=========onDestroy==========");
        super.onDestroy();
        try {
            if (isRegistered) {
                unregisterReceiver(mGeoFenceReceiver);
                isRegistered = false;
            }
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }


    List<SafeZoneLocation.FencesBean> mFenceAlarmDTOList = new ArrayList<>();
    /**
     * 接收触发围栏后的广播,当添加围栏成功之后，会立即对所有围栏状态进行一次侦测，如果当前状态与用户设置的触发行为相符将会立即触发一次围栏广播；
     * 只有当触发围栏之后才会收到广播,对于同一触发行为只会发送一次广播不会重复发送，除非位置和围栏的关系再次发生了改变。
     */
    private final BroadcastReceiver mGeoFenceReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            // 接收广播
            if (intent.getAction().equals(GEOFENCE_BROADCAST_ACTION)) {
                //mHandler.removeMessages(START_LOCATION);
                SafeZoneLocation.FencesBean fenceAlarmDTO = new SafeZoneLocation.FencesBean();
                Bundle bundle = intent.getExtras();
                String customId = bundle.getString(GeoFence.BUNDLE_KEY_CUSTOMID);
                String fenceId = bundle.getString(GeoFence.BUNDLE_KEY_FENCEID);
                //status标识的是当前的围栏状态，不是围栏行为
                int status = bundle.getInt(GeoFence.BUNDLE_KEY_FENCESTATUS);
                switch (status) {
                    case GeoFence.STATUS_LOCFAIL:
                        Logger.e(TAG, "定位失败");
                        break;
                    case GeoFence.STATUS_IN:
                        Logger.e(TAG, "进入围栏");
                        fenceAlarmDTO.alarmType = 1;
                        break;
                    case GeoFence.STATUS_OUT:
                        Logger.e(TAG, "离开围栏");
                        fenceAlarmDTO.alarmType = 0;
                        break;
                    case GeoFence.STATUS_STAYED:
                        Logger.e(TAG, "停留在围栏内");
                        break;
                    default:
                        break;
                }
                if (status != GeoFence.STATUS_LOCFAIL) {
                    if (!TextUtils.isEmpty(customId)) {
                        fenceAlarmDTO.id = Long.parseLong(customId);
                        mFenceAlarmDTOList.add(fenceAlarmDTO);
//                        mHandler.sendEmptyMessageDelayed(START_LOCATION, 2000);
                        //启动定位
                        LocationProto.LocationDetail.Builder locBuilder = LocationProto.LocationDetail.newBuilder()
                                .setHolderId(DataProvider.getHolderId())
                                .setEventId(UUID.randomUUID().toString())
                                .setStartTime(System.currentTimeMillis());
                        startLocation(locBuilder);
                    }
                }
            }
        }
    };

    private final Handler mHandler = new Handler(msg -> {
        if (msg.what == START_LOCATION) {
            //启动定位
            LocationProto.LocationDetail.Builder locBuilder = LocationProto.LocationDetail.newBuilder()
                    .setHolderId(DataProvider.getHolderId())
                    .setEventId(UUID.randomUUID().toString())
                    .setStartTime(System.currentTimeMillis());
            startLocation(locBuilder);
        }
        return false;
    });

    private void startLocation(LocationProto.LocationDetail.Builder locBuilder) {
        if (mLocationClient == null) {
            mLocationClient = new AMapLocationClient(this);
            mLocationOption = new AMapLocationClientOption();
            // 设置定位监听
            mLocationClient.setLocationListener(new AMapLocationCallback(locBuilder));
            // 设置为高精度定位模式
            mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
            // 只是为了获取当前位置，所以设置为单次定位
            mLocationOption.setOnceLocation(true);
            // 设置定位参数
            mLocationClient.setLocationOption(mLocationOption);
            mLocationClient.startLocation();
        }
    }

    private class AMapLocationCallback implements AMapLocationListener {

        private LocationProto.LocationDetail.Builder locBuilder;

        public AMapLocationCallback(LocationProto.LocationDetail.Builder locBuilder) {
            this.locBuilder = locBuilder;
        }

        @Override
        public void onLocationChanged(AMapLocation aMapLocation) {
            Logger.e(TAG, "AMapLocationListener$onLocationChanged " + aMapLocation);
            if (aMapLocation != null && aMapLocation.getErrorCode() == 0) {
                if (mLocationClient != null) {
                    mLocationClient.stopLocation();
                    mLocationClient.onDestroy();
                }
                mLocationClient = null;
                //上传安全区域事件

                String currentCellTower;
                List<String> nearCellTowers;
                List<LocationProto.WifiPoint> wifiPoints;
                try {
                    currentCellTower = CellInfoObserver.getInstance().getCurrentCellTower();
                } catch (Exception e) {
                    e.printStackTrace();
                    currentCellTower = "";
                }
                try {
                    nearCellTowers = CellInfoObserver.getInstance().getNearByCellTowers();
                } catch (Exception e) {
                    e.printStackTrace();
                    nearCellTowers = null;
                }
                try {
                    wifiPoints = Utils.getWifiPoints();
                } catch (Exception e) {
                    e.printStackTrace();
                    wifiPoints = null;
                }

                locBuilder.setEndTime(System.currentTimeMillis())
                        .setLocMode(getLocMode(aMapLocation))
                        .setOrder(32)
                        .setLat(aMapLocation.getLatitude())
                        .setLng(aMapLocation.getLongitude())
                        .setAccuracy(aMapLocation.getAccuracy())
                        .setSpeed(aMapLocation.getSpeed())
                        .setBattery(BaseApp.getInstance().getBatteryLevel())
                        .setCellTower(currentCellTower)
                        .addAllNearbyCellTowers(nearCellTowers)
                        .addAllWifiPoints(wifiPoints)
                        .setNetwork(NetUtils.getNetworkTypeName())
                        .setCoordType(getCoordType(aMapLocation.getCoordType()))
                        .setAddress(aMapLocation.getAddress())
                        .setCharge(BaseApp.getInstance().isCharging());

                ApiService.uploadSafeZoneEvent(mFenceAlarmDTOList, locBuilder.build(), new IPublishListener() {
                    @Override
                    public void onSuccess(ARequest request, AResponse response) {
                        Logger.d(TAG, "onSuccess:->" + response.data.toString());
                        JSONObject jsonObject = JSONObject.parseObject(response.data.toString());
                        int errCode = jsonObject.getIntValue("ERR_CODE");
                        if (errCode == 0) {
                            Logger.i("上传安全区域事件成功");
                            //清空缓存记录
                            mFenceAlarmDTOList.clear();
                        } else {
                            Logger.e(TAG, "ERR_MSG:" + jsonObject.getIntValue("ERR_MSG"));
                        }
                    }

                    @Override
                    public void onFailure(ARequest request, Object message, AError error) {
                        Logger.i("上传安全区域事件失败");
                    }
                });
            }
        }
    }


    @NotNull
    private LocationProto.LocMode getLocMode(AMapLocation loc) {
        LocationProto.LocMode locMode = LocationProto.LocMode.UNKNOWN;
        final int locationType = loc.getLocationType();
        switch (locationType) {
            case AMapLocation.LOCATION_TYPE_GPS:
                locMode = LocationProto.LocMode.GPS;
                break;
            case AMapLocation.LOCATION_TYPE_WIFI:
                locMode = LocationProto.LocMode.WIFI;
                break;
            case AMapLocation.LOCATION_TYPE_SAME_REQ:
            case AMapLocation.LOCATION_TYPE_FIX_CACHE:
            case AMapLocation.LOCATION_TYPE_CELL:
                locMode = LocationProto.LocMode.LBS;
                break;
            default:
                break;
        }
        return locMode;
    }

    private int getCoordType(String coordType) {
        if (TextUtils.isEmpty(coordType)) {
            return 1;
        }

        if (AMapLocation.COORD_TYPE_WGS84.equals(coordType)) {
            return 1;
        } else if (AMapLocation.COORD_TYPE_GCJ02.equals(coordType)) {
            return 2;
        }
        return 1;
    }

}
